package com.bub.pay.mq.consumer.service;

import com.alibaba.fastjson.JSONObject;
import com.bub.pay.core.entity.domain.SysKvPairEntry;
import com.bub.pay.core.manager.system.SysKvPairEntryManager;
import com.bub.pay.framework.common.base.Cause;
import com.bub.pay.framework.common.constant.SystemConstants;
import com.bub.pay.framework.common.exception.GlobalException;
import com.bub.pay.framework.common.util.HttpHelper;
import com.bub.pay.framework.common.util.RsaKeyHelper;
import com.google.common.collect.ImmutableMap;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.security.rsa.crypto.RsaRawEncryptor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/*@Service
public class CallbackNotifyServiceImpl implements CallbackNotifyService {

    private final Logger log = LoggerFactory.getLogger(CallbackNotifyServiceImpl.class);

    @Resource
    private PayOrderManager payOrderManager;

    @Resource
    private AliBankCardPayOrderManager aliBankCardPayOrderManager;

    @Resource
    private AliAccountPayOrderManager aliAccountPayOrderManager;

    @Resource
    private RemitOrderManager remitOrderManager;

    @Resource
    private MerchantKeyManager merchantKeyManager;

    @Resource
    private NotifyRecordManager notifyRecordManager;

    @Resource
    private SysKvPairEntryManager sysKvPairEntryManager;

    @Resource
    private WxInternationalPayOrderManager wxInternationalPayOrderManager;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String payOrderNotify(Map<String, Object> bodyMap) {
        String orderNo = bodyMap.get("orderNo").toString(); // 订单号
        int finalState = Integer.parseInt(bodyMap.get("finalState").toString()); // 成功状态
        int orderType = getOrderType(bodyMap);

        OrderObject payOrder = queryOrderObj(orderType, orderNo);
        if (payOrder.getOrderState() != finalState) {
            log.error("支付订单状态非成功状态,orderNo:{}", orderNo);
            throw new GlobalException(Cause.unknown);
        }
        // 获取秘钥信息
        MerchantSecretKey secretKey = merchantKeyManager.queryMerchantSecretKey(payOrder.getMerId(), SystemConstants.MERCHANT_TYPE_PAY_KEY);
        if (Objects.isNull(secretKey)) {
            log.error("支付秘钥未找到,merId:{},orderNo:{}", payOrder.getMerId(), payOrder.getOrderNo());
            throw new GlobalException(Cause.unknown);
        }
        SortedMap<String, Object> dataMap = new TreeMap<>();
        dataMap.put("orderNo", payOrder.getOrderNo());
        dataMap.put("merOrderNo", payOrder.getMerOrderNo());
        int transState = payOrder.getOrderState() == PayOrderStateEnum.PAY_SUCCESS_STATE.getCode() ? 1 :
                payOrder.getOrderState() == PayOrderStateEnum.PAY_ORDER_FAIL.getCode() ? 2 : 0;
        dataMap.put("orderState", transState);
        dataMap.put("amount", payOrder.getOrderAmount().stripTrailingZeros().toPlainString());

        StringBuilder signSourceStr = new StringBuilder();
        dataMap.forEach((k, v) -> signSourceStr.append(k).append("=").append(v).append("&"));
        signSourceStr.append("key=" + secretKey.getSignKey());

        log.info("signSourceStr:{}", signSourceStr);

        dataMap.put("sign", DigestUtils.md5Hex(signSourceStr.toString()).toUpperCase());

//        dataMap.put("realAmount", payOrder.getRealAmount().stripTrailingZeros().toPlainString());
//        dataMap.put("qrCodeAmount", payOrder.getQrCodeAmount().stripTrailingZeros().toPlainString());

        log.info("支付回调请求报文:{}", dataMap.toString());
        String enData;
        try {
            enData = new RsaRawEncryptor(SystemConstants.DEFAULT_CODE, RsaKeyHelper.parsePublicKey(secretKey.getPublicKey())
                    , null).encrypt(JSONObject.toJSONString(dataMap));
        } catch (Exception e) {
            log.error("数据加密错误", e);
            throw new GlobalException(Cause.unknown);
        }
        // 使用http回调下游
        String resData;
        Map<String, String> callMap = ImmutableMap.of("merId", String.valueOf(payOrder.getMerId()), "merOrderNo", payOrder.getMerOrderNo(), "data", enData);
        try {
            Example example = new Example(SysKvPairEntry.class);
            example.createCriteria().andEqualTo("baseKey", "PROXY_HOST_IP_PORT");
            SysKvPairEntry kvPairEntry = sysKvPairEntryManager.getOneByExample(example);
            String[] ipPortArr = kvPairEntry.getBaseValue().split(":");
            resData = HttpHelper.postJSONByProxy(payOrder.getNoticeUrl(), JSONObject.toJSONString(callMap), ipPortArr[0], Integer.parseInt(ipPortArr[1]));
        } catch (Exception e) {
            log.error("回调下游异常", e);
            resData = e.getMessage();
        }
        log.info("支付订单:{},回调响应文本:{}", orderNo, resData);
        // 返回成功则修改订单回调状态
        updateOrderByOrderType(orderType,payOrder,resData);
        try {
            // 增加回调记录
            NotifyRecord record = new NotifyRecord();
            record.setBusinessNo(payOrder.getOrderNo());
            record.setMerId(payOrder.getMerId());
            record.setNotifyData(JSONObject.toJSONString(callMap));
            record.setNotifyType(1);
            record.setNotifyData(resData);
            notifyRecordManager.insertSelective(record);
        } catch (Exception e) {
            log.error("插入回调记录异常", e);
        }
        return resData;
    }

    private int getOrderType(Map<String, Object> bodyMap) {
        Object orderType = bodyMap.get("orderType");
        if (orderType == null) {
            return OrderTypeEnum.ALI_BANK_CARD.getType();
        }
        return Integer.valueOf(orderType.toString());
    }

    @Override
    public String remitOrderNotify(Map<String, String> bodyMap) {
        String orderNo = bodyMap.get("orderNo"); // 订单号
        int finalState = Integer.parseInt(bodyMap.get("finalState")); // 代付订单回调状态
        Example orderExample = new Example(PayOrder.class);
        orderExample.createCriteria().andEqualTo("orderNo", orderNo);
        RemitOrder remitOrder = remitOrderManager.getOneByExample(orderExample);
        if (Objects.isNull(remitOrder)) {
            log.error("代付订单不存在,orderNo:{}", orderNo);
            throw new GlobalException(Cause.unknown);
        }
        if (remitOrder.getOrderState() != finalState) {
            log.error("代付订单状态成功状态,orderNo:{}", orderNo);
            throw new GlobalException(Cause.unknown);
        }
        // 获取秘钥信息
        MerchantSecretKey secretKey = merchantKeyManager.queryMerchantSecretKey(remitOrder.getMerId(), SystemConstants.MERCHANT_TYPE_REMIT_KEY);
        if (Objects.isNull(secretKey)) {
            log.error("代付秘钥未找到,merId:{},orderNo:{}", remitOrder.getMerId(), remitOrder.getOrderNo());
            throw new GlobalException(Cause.unknown);
        }
        SortedMap<String, Object> dataMap = new TreeMap<>();
        dataMap.put("orderNo", remitOrder.getOrderNo());
        dataMap.put("merOrderNo", remitOrder.getMerOrderNo());
        int transState = remitOrder.getOrderState().intValue() == RemitOrderStateEnum.REMIT_SUCCESS.getCode() ? 1 :
                remitOrder.getOrderState().intValue() == RemitOrderStateEnum.REMIT_FAIL_REFUND.getCode() ? 2 : 0;
        dataMap.put("orderState", transState);
        dataMap.put("amount", new BigDecimal(remitOrder.getOrderAmount().stripTrailingZeros().toPlainString()));

        StringBuilder sb = new StringBuilder();
        dataMap.forEach((k, v) -> sb.append(k).append("=").append(v).append("&"));
        sb.append("key=" + secretKey.getSignKey());
        dataMap.put("sign", DigestUtils.md5Hex(sb.toString()).toUpperCase());
        log.info("代付回调请求报文:{}", dataMap.toString());
        String enData;
        try {
            enData = new RsaRawEncryptor(SystemConstants.DEFAULT_CODE, RsaKeyHelper.parsePublicKey(secretKey.getPublicKey())
                    , null).encrypt(JSONObject.toJSONString(dataMap));
        } catch (Exception e) {
            log.error("数据加密错误", e);
            throw new GlobalException(Cause.unknown);
        }
        // 使用http回调下游
        String resData;
        Map<String, String> callMap = ImmutableMap.of("merId", String.valueOf(remitOrder.getMerId()), "merOrderNo", remitOrder.getMerOrderNo(), "data", enData);
        try {
            Example example = new Example(SysKvPairEntry.class);
            example.createCriteria().andEqualTo("baseKey", "PROXY_HOST_IP_PORT");
            SysKvPairEntry kvPairEntry = sysKvPairEntryManager.getOneByExample(example);
            String[] ipPortArr = kvPairEntry.getBaseValue().split(":");
            resData = HttpHelper.postJSONByProxy(remitOrder.getNotifyUrl(), JSONObject.toJSONString(callMap), ipPortArr[0], Integer.parseInt(ipPortArr[1]));
        } catch (Exception e) {
            log.error("回调下游异常", e);
            resData = e.getMessage();
        }
        log.info("代付订单:{},回调响应文本:{}", orderNo, resData);
        // 返回成功则修改订单回调状态
        RemitOrder updateOrder = new RemitOrder();
        updateOrder.setId(remitOrder.getId());
        updateOrder.setNotifyCount(remitOrder.getNotifyCount() + 1);
        if (resData != null && "success".equalsIgnoreCase(resData)) {
            updateOrder.setNotifyDate(new Date());
            updateOrder.setNotifyState(1);
        }
        remitOrderManager.updateByPrimaryKeySelective(updateOrder);
        try {
            // 增加回调记录
            NotifyRecord record = new NotifyRecord();
            record.setBusinessNo(remitOrder.getOrderNo());
            record.setMerId(remitOrder.getMerId());
            record.setNotifyData(JSONObject.toJSONString(callMap));
            record.setNotifyType(2); // 1 = 支付, 2 = 代付
            record.setNotifyData(resData);
            notifyRecordManager.insertSelective(record);
        } catch (Exception e) {
            log.error("插入回调记录异常", e);
        }
        return resData;
    }
    //查询对应订单
    private OrderObject queryOrderObj(int orderType, String orderNo) {
        OrderTypeEnum orderTypeEnum = OrderTypeEnum.valueOfType(orderType);
        if (orderTypeEnum == null) {
            throw new IllegalArgumentException("未知订单类型");
        }
        OrderObject orderObject= new OrderObject();
        switch (orderTypeEnum) {
            case PAY://网银
                Example payOrderExample = new Example(PayOrder.class);
                payOrderExample.createCriteria().andEqualTo("orderNo", orderNo);
                PayOrder payOrder = payOrderManager.getOneByExample(payOrderExample);
                if (Objects.isNull(payOrder)) {
                    log.error("支付订单不存在,orderNo:{}", orderNo);
                    throw new GlobalException(Cause.unknown);
                }
                BeanUtils.copyProperties(payOrder, orderObject);
                break;
            case ALI_BANK_CARD://支付宝银行扫码
                Example aliBankCardPayOrderExample = new Example(AliBankCardPayOrder.class);
                aliBankCardPayOrderExample.createCriteria().andEqualTo("orderNo", orderNo);
                AliBankCardPayOrder aliAccountPayOrder = aliBankCardPayOrderManager.getOneByExample(aliBankCardPayOrderExample);
                if (Objects.isNull(aliAccountPayOrder)) {
                    log.error("支付订单不存在,orderNo:{}", orderNo);
                    throw new GlobalException(Cause.unknown);
                }
                BeanUtils.copyProperties(aliAccountPayOrder, orderObject);
                break;
            case ALI_ACCOUNT:
                Example aliAccountPayOrderExample = new Example(AliAccountPayOrder.class);
                aliAccountPayOrderExample.createCriteria().andEqualTo("orderNo", orderNo);
                AliAccountPayOrder accountPayOrder = aliAccountPayOrderManager.getOneByExample(aliAccountPayOrderExample);
                if (Objects.isNull(accountPayOrder)) {
                    log.error("支付订单不存在,orderNo:{}", orderNo);
                    throw new GlobalException(Cause.unknown);
                }
                BeanUtils.copyProperties(accountPayOrder, orderObject);
                break;
            case WX_INTERNATIONAL:
                Example wxInternationalPayOrderExample = new Example(WxInternationalPayOrder.class);
                wxInternationalPayOrderExample.createCriteria().andEqualTo("orderNo", orderNo);
                WxInternationalPayOrder wxInternationalPayOrder = wxInternationalPayOrderManager.getOneByExample(wxInternationalPayOrderExample);
                if (Objects.isNull(wxInternationalPayOrder)) {
                    log.error("支付订单不存在,orderNo:{}", orderNo);
                    throw new GlobalException(Cause.unknown);
                }
                BeanUtils.copyProperties(wxInternationalPayOrder, orderObject);
                break;
            default :
                throw new GlobalException(Cause.operat_fail);
        }
        return orderObject;
    }
    //更新对应订单
    private void updateOrderByOrderType(int orderType,OrderObject payOrder,String resData){
        OrderTypeEnum orderTypeEnum = OrderTypeEnum.valueOfType(orderType);
        if (orderTypeEnum == null) {
            throw new IllegalArgumentException("未知订单类型");
        }
        switch (orderTypeEnum) {
            case PAY://网银
                PayOrder updateOrder = new PayOrder();
                updateOrder.setId(payOrder.getId());
                updateOrder.setNotifyCount(payOrder.getNotifyCount() + 1);
                if (resData != null && "success".equalsIgnoreCase(resData)) {
                    updateOrder.setNoticeState(1);
                    updateOrder.setNoticeSuccessDate(new Date());
                }
                payOrderManager.updateByPrimaryKeySelective(updateOrder);
                break;
            case ALI_BANK_CARD://支付宝转银行扫码
                AliBankCardPayOrder updateAliBankCardPayOrder = new AliBankCardPayOrder();
                updateAliBankCardPayOrder.setId(payOrder.getId());
                updateAliBankCardPayOrder.setNotifyCount(payOrder.getNotifyCount() + 1);
                if (resData != null && "success".equalsIgnoreCase(resData)) {
                    updateAliBankCardPayOrder.setNoticeState(1);
                    updateAliBankCardPayOrder.setNoticeSuccessDate(new Date());
                }
                aliBankCardPayOrderManager.updateByPrimaryKeySelective(updateAliBankCardPayOrder);
                break;
            case ALI_ACCOUNT://支付宝转支付宝扫码
                AliAccountPayOrder updateAliAccountPayOrder = new AliAccountPayOrder();
                updateAliAccountPayOrder.setId(payOrder.getId());
                updateAliAccountPayOrder.setNotifyCount(payOrder.getNotifyCount() + 1);
                if (resData != null && "success".equalsIgnoreCase(resData)) {
                    updateAliAccountPayOrder.setNoticeState(1);
                    updateAliAccountPayOrder.setNoticeSuccessDate(new Date());
                }
                aliAccountPayOrderManager.updateByPrimaryKeySelective(updateAliAccountPayOrder);
                break;
            case WX_INTERNATIONAL:
                WxInternationalPayOrder updateWxInternationalPayOrder = new WxInternationalPayOrder();
                updateWxInternationalPayOrder.setId(payOrder.getId());
                updateWxInternationalPayOrder.setNotifyCount(payOrder.getNotifyCount() + 1);
                if (resData != null && "success".equalsIgnoreCase(resData)) {
                    updateWxInternationalPayOrder.setNoticeState(1);
                    updateWxInternationalPayOrder.setNoticeSuccessDate(new Date());
                }
                wxInternationalPayOrderManager.updateByPrimaryKeySelective(updateWxInternationalPayOrder);
                break;
            default :
                throw new GlobalException(Cause.operat_fail);
        }
    }

    @Getter
    @Setter
    class OrderObject{
        private Long id;
        private Integer orderState;
        private Long merId;
        private String orderNo;
        private String merOrderNo;
        private BigDecimal orderAmount;

        *//**
         * 实际支付金额
         *//*
        private BigDecimal realAmount;

        *//**
         * 二维码金额
         *//*
        private BigDecimal qrCodeAmount;

        private String noticeUrl;
        private Integer notifyCount;
    }


}*/
